#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "liso_engine.h"
#include "http_parser.h"
#include "liso_logging.h"

#define USAGE "%s <HTTP port> <HTTPS port> <log file> <lock file> <www folder>\
 <CGI folder or script name> <private key file> <certificate file>\n"

void signal_handler(int sig);
int daemonize(char* lock_file);

int main(int argc, char *argv[])
{
	int port, sslport;
	char *log, *lock, *www, *cgi, *pkey, *cert;
	if (argc < 9) {
		printf(USAGE, argv[0]);
		return EXIT_FAILURE;
	}

	port = atoi(argv[1]);
	sslport = atoi(argv[2]);
	log = argv[3];
	lock = argv[4];
	www = argv[5];
	cgi = argv[6];
	pkey = argv[7];
	cert = argv[8];

	daemonize(lock);
	
	select_engine_t engine;
	liso_logging_create_log_file(log);
	liso_engine_create(&engine, port, sslport, log, lock, www, cgi, pkey, cert);
	liso_engine_register_http_handler(&engine, parser_http_handler);
	liso_logging_log("liso", "main", "Starting Liso server on port %d and %d\n", 
						port, sslport);

	return liso_engine_event_loop(&engine);
}

void signal_handler(int sig)
{
	switch (sig)
	{
		case SIGHUP:
			break;
		case SIGTERM:
			liso_engine_shut_down(EXIT_SUCCESS);
			break;
		default:
			break;
	}
}

int daemonize(char* lock_file)
{
	/* drop to having init() as parent */
	int i, lfp, pid = fork();
	char str[256] = {0};
	if (pid < 0) exit(EXIT_FAILURE);
	if (pid > 0) exit(EXIT_SUCCESS);

	setsid();

	for (i = getdtablesize(); i >= 0; i--)
		close(i);

	i = open("/dev/null", O_RDWR);
	dup(i);	/* stdout */
	dup(i);	/* stderr */
	umask(027);

	lfp = open(lock_file, O_RDWR|O_CREAT|O_EXCL, 0640);

	if (lfp < 0) {
		fprintf(stderr, "Can not open lockfile.\n");
		exit(EXIT_FAILURE);
	}

	if (lockf(lfp, F_TLOCK, 0) < 0) {
		fprintf(stderr, "Can not lock lockfile.\n");
		exit(EXIT_FAILURE);
	}

	/* only first instance continues */
	sprintf(str, "%d\n", getpid());
	write(lfp, str, strlen(str));	/* record pid to lockfile */

	signal(SIGCHLD, SIG_IGN);
	signal(SIGHUP, signal_handler);	/* hangup signal */
	signal(SIGTERM, signal_handler);	/* software termination signal from kill */

	return EXIT_SUCCESS;
}
